home *** CD-ROM | disk | FTP | other *** search
- /*********************/
- /* PrimeThreadsApp.m */
- /*********************/
- #import "PrimeThreadsApp.h"
- #import <appkit/Button.h>
- #import <appkit/Control.h>
- #import <appkit/chunk.h>
- #import <dpsclient/dpsNeXT.h>
- #import <math.h>
-
- /* the code is much smaller when you take out the comments ;-) */
-
- /*
- * thePrimeList is maintained by the NXChunk system. GROW_BY
- * is how much the structure's malloc'ed space will grow, when
- * it needs to be expanded. The chunk is also initialized
- * with GROW_BY bytes.
- */
- #define GROW_BY 8192
- /* every UPDATE_PERIOD seconds, a timed entry calls updateFieldsGlue */
- #define UPDATE_PERIOD 0.25
-
- struct primeList {
- /* see /usr/include/appkit/chunk.h for a description of the NXChunk */
- NXChunk chunk;
- /* number of primes in the list */
- int numPrimes;
- /* This is just a bogus declaration. There can be any number of primes. */
- int thePrimes[2];
- } *thePrimeList;
-
- /* this mutex guards thePrimeList */
- mutex_t primeListLock;
-
- /* this is the function the timed entry calls */
- void updateFieldsGlue(DPSTimedEntry te, double now, void *self)
- /* we, in turn, call the updateFields method (we're just glue) */
- { [(id)self updateFields]; }
-
- /* findPrimes is executed on its own thread. it never stops. */
- void findPrimes(int ignored)
- {
- int counter, possiblePrime = 5, testLimit;
- BOOL isPrime;
-
- while (YES) /* repeat forever */
- {
- /* isPrime starts at YES. if an exact divisor is found, it becomes NO */
- isPrime = YES;
- /* for any non-prime integer x, one of its factors is less than sqrt(x) */
- testLimit = sqrt(possiblePrime);
- for (counter=1; isPrime && (thePrimeList->thePrimes[counter]<=testLimit); counter++)
- if (possiblePrime % thePrimeList->thePrimes[counter] == 0)
- isPrime = NO;
- if (isPrime)
- {
- /* lock the mutex before changing the list */
- mutex_lock(primeListLock);
- /* another prime for the list! */
- thePrimeList->numPrimes++;
- /*
- * grow the chunk. usually this does nothing; sometimes more
- * space gets allocated.
- */
- thePrimeList =
- (struct primeList *)NXChunkGrow((NXChunk *)thePrimeList,
- thePrimeList->numPrimes * sizeof(int));
- /* place our newly-certified prime into the list. */
- thePrimeList->thePrimes[thePrimeList->numPrimes - 1] = possiblePrime;
- /* unlock the mutex now that we're done with the list */
- mutex_unlock(primeListLock);
- }
- possiblePrime += 2; /* don't bother with even numbers */
- /* tell the scheduler that this is a convenient time to run other threads */
- cthread_yield();
- }
- }
-
- @implementation PrimeThreadsApp
-
- /* IB outlets */
- - setNumPrimesField:anObject
- { numPrimesField = anObject; return self; }
- - setHighestPrimeField:anObject
- { highestPrimeField = anObject; return self; }
-
- - appDidInit:sender
- {
- /* allocate the mutex */
- primeListLock = mutex_alloc();
- /*
- * initialize thePrimeList with GROW_BY bytes of memory
- * to start with, and make it grow by GROW_BY bytes when
- * it expands.
- */
- thePrimeList = (struct primeList *)NXChunkMalloc(GROW_BY, GROW_BY);
- /* we start the list with 2 primes: 2 and 3. */
- thePrimeList->numPrimes = 2;
- thePrimeList->thePrimes[0] = 2;
- thePrimeList->thePrimes[1] = 3;
- /*
- * start up the primeFinderThread. It will never stop, but we can
- * suspend and resume the thread, which is just as good.
- */
- primeFinderThread = cthread_fork(findPrimes, 0);
- /* since we will never want to join the thread, we detach it. */
- cthread_detach(primeFinderThread);
- /* create the timed entry that will handle updating the fields */
- DPSAddTimedEntry(UPDATE_PERIOD, updateFieldsGlue,
- (void *)self, NX_BASETHRESHOLD);
- return self;
- }
-
- - toggleGoStop:sender
- {
- /*
- * cthread_thread gets us the actual thread, which is a part of
- * the cthread structure. struct cthread has a lot of other neat
- * stuff in it, too, but we don't (explicitly) use any of it.
- * thread_resume() and thread_suspend() just want the thread identifier,
- * not a cthread, and we give it to 'em.
- */
- if ([sender state] == YES) /* turn it on */
- thread_resume(cthread_thread(primeFinderThread));
- else /* turn it off */
- thread_suspend(cthread_thread(primeFinderThread));
- return self;
- }
-
- - updateFields
- {
- /* lock the mutex before reading the list */
- mutex_lock(primeListLock);
- [numPrimesField setIntValue:thePrimeList->numPrimes];
- [highestPrimeField setIntValue:thePrimeList->thePrimes[thePrimeList->numPrimes - 1]];
- /* unlock the mutex, now that we're done with the list */
- mutex_unlock(primeListLock);
- return self;
- }
-
- @end
-